﻿using System;
using System.Collections;
using System.Collections.Generic;
using Common.Utils;
using UnityEngine;
using UnityEngine.Networking;
using USClientKernel.Template;

namespace NetFramework.HTTP
{
    public delegate void HTTPResult(UnityWebRequest result);
    public delegate void HTTPSucceed<T>(T obj);
    public delegate void HTTPFailed(long errCode, string errMsg);
    public delegate void HTTPProgress(float progress, ulong compBytes = 0, ulong totalBytes = 0);

    public class HTTPManager : Singleton<HTTPManager>
    {

        /// <summary>
        /// 向服务器提交Get请求
        /// </summary>
        /// <param name="_url">服务器地址,like 'http://www.my-server.com/'</param>
        /// <param name="_cb">请求发起后处理回调结果的委托</param>
        /// <returns></returns>
        public void Get(string _url, HTTPResult _cb)
        {
            CoroutineController.Instance.StartCoroutine(_Get(_url, _cb));
        }


        /// <summary>
        /// 向服务器提交Post请求
        /// </summary>
        /// <param name="_url">服务器地址,like 'http://www.my-server.com/'</param>
        /// <param name="_form">要提交的所有表单数据</param>
        /// <param name="_cb">请求发起后处理回调结果的委托</param>
        /// <returns></returns>
        public void Post(string _url, List<IMultipartFormSection> _form, HTTPResult _cb)
        {
            CoroutineController.Instance.StartCoroutine(_Post(_url, _form, _cb));
        }


        /// <summary>
        /// 获取服务器文件信息
        /// </summary>
        /// <param name="_url">下载的服务器文件地址,like 'http://www.my-server.com/fileName.txt'</param>
        /// <param name="_cb">请求发起后处理回调结果的委托</param>
        /// <returns></returns>
        public void TouchFile(string _url, HTTPResult _cb)
        {
            CoroutineController.Instance.StartCoroutine(_TouchFile(_url, _cb));
        }


        /// <summary>
        /// 从服务器下载文件
        /// </summary>
        /// <param name="_url">下载的服务器文件地址,like 'http://www.my-server.com/fileName.txt'</param>
        /// <param name="_fullName">文件全路径和文件名称</param>
        /// <param name="_cb">请求发起后处理回调结果的委托</param>
        /// <param name="_progress">请求发起后的进度委托</param>
        /// <returns></returns>
        public void DownloadFile(string _url, string _fullName, HTTPResult _cb, HTTPProgress _progress)
        {
            CoroutineController.Instance.StartCoroutine(_DownloadFile(_url, _fullName, _cb, _progress));
        }


        /// <summary>
        /// 上传文件到服务器
        /// </summary>
        /// <param name="_url">上传的服务器地址,like 'http://www.my-server.com/'</param>
        /// <param name="_strBuffer">原始数据的string buffer</param>
        /// <param name="_fileName">文件名称</param>
        /// <param name="_cb">请求发起后处理回调结果的委托</param>
        /// <param name="_progress">请求发起后的进度委托</param>
        /// <returns></returns>
        public void UploadFile(string _url, string _strBuffer, string _name, HTTPResult _cb, HTTPProgress _progress)
        {
            CoroutineController.Instance.StartCoroutine(_UploadFile(_url, _strBuffer, _name, _cb, _progress));
        }


        /// <summary>
        /// 上传文件到服务器
        /// </summary>
        /// <param name="_url">AssetBundle地址,like 'http://www.my-server.com/myData.unity3d'</param>
        /// <param name="_succeed">请求发起后处理成功回调结果的委托,回调参数为请求结果的AssetBundle</param>
        /// <param name="_failed">请求发起后处理失败回调结果的委托,回调参数为错误码和错误消息</param>
        /// <returns></returns>
        public void GetAssetBundle(string _url, HTTPSucceed<AssetBundle> _succeed, HTTPFailed _failed = null)
        {
            CoroutineController.Instance.StartCoroutine(_GetAssetBundle(_url, _succeed, _failed));
        }


        /// <summary>
        /// 向服务器提交Get请求
        /// </summary>
        /// <param name="_url">下载的服务器文件地址,like 'http://www.my-server.com/'</param>
        /// <param name="_cb">请求发起后处理回调结果的委托</param>
        /// <returns></returns>
        private IEnumerator _Get(string url, HTTPResult cb)
        {
            UnityWebRequest uwr = UnityWebRequest.Get(url);
            yield return uwr.SendWebRequest();
            if (cb != null)
            {
                cb(uwr);
            }
        }


        /// <summary>
        /// 向服务器提交Post请求
        /// </summary>
        /// <param name="_url">下载的服务器文件地址,like 'http://www.my-server.com/'</param>
        /// <param name="_form">要提交的所有表单数据</param>
        /// <param name="_cb">请求发起后处理回调结果的委托</param>
        /// <returns></returns>
        private IEnumerator _Post(string url, List<IMultipartFormSection> _form, HTTPResult cb)
        {
            UnityWebRequest uwr = UnityWebRequest.Post(url, _form);
            yield return uwr.SendWebRequest();
            if (cb != null)
            {
                cb(uwr);
            }
        }


        /// <summary>
        /// 获取服务器文件信息
        /// </summary>
        /// <param name="_url">下载的服务器文件地址,like 'http://www.my-server.com/fileName.txt'</param>
        /// <param name="_cb">请求发起后处理回调结果的委托</param>
        /// <returns></returns>
        private IEnumerator _TouchFile(string _url, HTTPResult _cb)
        {
            var uwr = new UnityWebRequest(_url, UnityWebRequest.kHttpVerbHEAD);
            uwr.downloadHandler = new DownloadHandlerBuffer();
            yield return uwr.SendWebRequest();

            if (uwr.isNetworkError || uwr.isHttpError)
                Debug.Log(uwr.error);
            if (uwr.isDone && null != _cb)
                _cb(uwr);
        }


        /// <summary>
        /// 从服务器下载文件
        /// </summary>
        /// <param name="_url">下载的服务器文件地址,like 'http://www.my-server.com/fileName.txt'</param>
        /// <param name="_fullName">文件全路径和文件名称</param>
        /// <param name="_cb">请求发起后处理回调结果的委托</param>
        /// <param name="_progress">请求发起后的进度委托</param>
        /// <returns></returns>
        private IEnumerator _DownloadFile(string _url, string _fullName, HTTPResult _cb, HTTPProgress _progress)
        {
            var uwr = new UnityWebRequest(_url, UnityWebRequest.kHttpVerbGET);
            uwr.downloadHandler = new DownloadHandlerFile(_fullName);
            yield return null;
            Debug.LogFormat("Start download file _url-->{0} to file-->{1}", _url, _fullName);
            uwr.SendWebRequest();
            var uwrp = uwr.GetResponseHeaders();

            while (!uwr.isDone)
            {
                ulong length = System.Convert.ToUInt64(uwr.GetResponseHeader("Content-Length"));
                if (null != _progress)
                    _progress(uwr.downloadProgress, uwr.downloadedBytes, length);
                Debug.LogFormat("Download progress->{0} downloadedBytes->{1} length->{2}", uwr.downloadProgress, uwr.downloadedBytes, length);
                yield return null;
            }

            Debug.LogFormat("Download progress->{0} downloadedBytes->{1} length->{2}", uwr.downloadProgress, uwr.downloadedBytes, System.Convert.ToUInt64(uwr.GetResponseHeader("Content-Length")));

            if (_cb != null)
                _cb(uwr);
        }


        /// <summary>
        /// 上传文件到服务器
        /// </summary>
        /// <param name="_url">上传的服务器地址,like 'http://www.my-server.com/'</param>
        /// <param name="_strBuffer">原始数据的string buffer</param>
        /// <param name="_fileName">文件名称</param>
        /// <param name="_cb">请求发起后处理回调结果的委托</param>
        /// <param name="_progress">请求发起后的进度委托</param>
        /// <returns></returns>
        private IEnumerator _UploadFile(string _url, string _strBuffer, string _fileName, HTTPResult _cb, HTTPProgress _progress)
        {
            var uwr = new UnityWebRequest(_url, UnityWebRequest.kHttpVerbPOST);
            ulong length = System.Convert.ToUInt64(_strBuffer.Length);
            List<IMultipartFormSection> formData = new List<IMultipartFormSection>();
            formData.Add(new MultipartFormFileSection(_strBuffer, _fileName));
            yield return null;
            uwr.SendWebRequest();

            while (!uwr.isDone)
            {
                if (null != _progress)
                    _progress(uwr.uploadProgress, uwr.uploadedBytes, length);
                yield return null;
            }

            if (_cb != null)
                _cb(uwr);
        }


        /// <summary>
        /// 上传原始数据到服务器
        /// </summary>
        /// <param name="_url">上传的服务器地址,like 'http://www.my-server.com/'</param>
        /// <param name="_data">原始数据</param>
        /// <param name="_cb">请求发起后处理回调结果的委托</param>
        /// <param name="_progress">请求发起后的进度委托</param>
        /// <param name="_contentType">内容类型</param>
        /// <returns></returns>
        private IEnumerator _UploadRaw(string _url, byte[] _data, HTTPResult _cb, HTTPProgress _progress, string _contentType = "application/octet-stream")
        {
            var uwr = new UnityWebRequest(_url, UnityWebRequest.kHttpVerbPUT);
            ulong length = System.Convert.ToUInt64(_data.Length);
            uwr.uploadHandler = new UploadHandlerRaw(_data);
            uwr.uploadHandler.contentType = _contentType;
            yield return null;
            uwr.SendWebRequest();

            while (!uwr.isDone)
            {
                if (null != _progress)
                    _progress(uwr.uploadProgress, uwr.uploadedBytes, length);
                yield return null;
            }

            if (_cb != null)
                _cb(uwr);
        }


        /// <summary>
        /// 请求图片
        /// </summary>
        /// <param name="_url">图片地址,like 'http://www.my-server.com/image.png '</param>
        /// <param name="_succeed">请求发起后处理成功回调结果的委托,回调参数为请求结果的图片</param>
        /// <param name="_failed">请求发起后处理失败回调结果的委托,回调参数为错误码和错误消息</param>
        /// <returns></returns>
        IEnumerator _GetTexture(string _url, HTTPSucceed<Texture2D> _succeed, HTTPFailed _failed = null)
        {
            var uwr = new UnityWebRequest(_url);
            var dht = new DownloadHandlerTexture(true);
            uwr.downloadHandler = dht;
            yield return uwr.SendWebRequest();

            if (uwr.isNetworkError || uwr.isHttpError)
            {
                if (null != _failed)
                    _failed(uwr.responseCode, uwr.error);
            }
            else if (uwr.isDone)
            {
                if (null != _succeed)
                    _succeed(dht.texture);
            }
        }


        /// <summary>
        /// 请求AssetBundle
        /// </summary>
        /// <param name="_url">AssetBundle地址,like 'http://www.my-server.com/myData.unity3d'</param>
        /// <param name="_succeed">请求发起后处理成功回调结果的委托,回调参数为请求结果的AssetBundle</param>
        /// <param name="_failed">请求发起后处理失败回调结果的委托,回调参数为错误码和错误消息</param>
        /// <returns></returns>
        IEnumerator _GetAssetBundle(string _url, HTTPSucceed<AssetBundle> _succeed, HTTPFailed _failed = null)
        {
            var uwr = new UnityWebRequest(_url);
            var dhab = new DownloadHandlerAssetBundle(uwr.url, uint.MaxValue);
            uwr.downloadHandler = dhab;
            yield return uwr.SendWebRequest();

            if (uwr.isNetworkError || uwr.isHttpError)
            {
                if (null != _failed)
                    _failed(uwr.responseCode, uwr.error);
            }
            else if (uwr.isDone)
            {
                if (null != _succeed)
                    _succeed(dhab.assetBundle);
            }
        }


        /// <summary>
        /// 请求服务器地址上的音效
        /// </summary>
        /// <param name="_url">AudioClip地址,like 'http://myserver.com/mysound.wav'</param>
        /// <param name="_succeed">请求发起后处理成功回调结果的委托,回调参数为请求结果的AudioClip</param>
        /// <param name="_failed">请求发起后处理失败回调结果的委托,回调参数为错误码和错误消息</param>
        /// <param name="_audioType">音效类型</param>
        /// <returns></returns>
        IEnumerator _GetAudioClip(string _url, HTTPSucceed<AudioClip> _succeed, HTTPFailed _failed = null, AudioType _audioType = AudioType.WAV)
        {
            var uwr = UnityWebRequestMultimedia.GetAudioClip(_url, _audioType);
            yield return uwr.SendWebRequest();

            if (uwr.isNetworkError || uwr.isHttpError)
            {
                if (null != _failed)
                    _failed(uwr.responseCode, uwr.error);
            }
            else if (uwr.isDone)
            {
                if (_succeed != null)
                    _succeed(DownloadHandlerAudioClip.GetContent(uwr));
            }
        }
    }
}
